Writing Secure Verbs (by EricM) Acknowledgment: This text is a formatted version of a message posted to ??? on BioMOO by: Copyright 1995 Eric Mercer last updated 7/11/95 EricM @ BioMOO, Diversity University, others.... mercer@caltech.edu Additional documentation: Check out the MOO programmer's manuel, e.g. the callers function. What verbs need permissions checking? Any verb that either 1. alters the state of the object in a way that only a limited number of people should be able to do, or 2. provides information that only a limited number of people should have access to. What are the main considerations in choosing a format for your security? The main considerations are 1) is the verb +x, and 2) can the verb be called from the command line (ie. does it have args other than this none this). Note that these are not linked and you can have +x command line verbs, for instance. What is the general structure of a permissions test? Verbs should start with a few lines of comments (describing what they do, etc.) followed by: if (perms_test_fails) return failure_report; endif ....->rest of verb where "failure_report" should be 'E_PERM' for +x this none this verbs, and 'player:tell("Sorry, you don't have permission to do that.")' for -x command line verb). For +x command line verbs, add the player:tell line before returning E_PERM. Replace "perms_test_fails" with one of the constructs given later in this note. What are valid calls to +x, this none this verbs? I think the following list is complete. I've also given an example of a typical "perms_test_fails" line for each, but note that you'll often want to use some combination or hybrid. 1. Calls from other verbs on the object itself. type:object-based security example: if (caller!=this) 2. Wiz-permed calls type: permissions-based security example: if (!$perm_utils:controls(caller_perms(), this)) <-preferred if (!caller_perms().wizard) <- less flexible 3. Calls from verbs owned by the same programmer type: perms-based security example: if (caller_perms() != $code_utils:verb_perms()) note: Gives a lot of power to the programmer, but sometimes useful. Note that we DON'T use the object number of the programmer, because this will be different if someone ports the object. 4. Calls from verbs owned by the object owner type:perms-based security example: if (caller_perms() != this.owner) note: rarely useful, and not at all useful on generic objects 5. Calls from objects owned by the programmer type: object-based security example: if (caller.owner != $code_utils:verb_perms()) note: only useful in some special cases 6. Calls from "permitted" objects (generally stored as a list on a property) type: object-based security example: if (!(caller in this.permitted_callers)) note: useful only in some specialized circumstances What is the most useful test for -x command line verbs? if (!$perm_utils:controls(player,this)) This allows the object owner, additional owners, or wizards access to the verb. Why is it unacceptable to test "player" for security on +x verbs? I'll give an example. Loro the lazy wizard writes a +x verb that can recycle any object and tests permissions with "if (!$perm_utils:controls(player,this))" at the verb's beginning. Semli the sneaky programmer builds an object and adds a "tell" verb to it (ie. a verb that gets called any time someone in the same room speaks). The "tell" verb calls Loro's +x verb and tells it to recycle all of Loro's objects. Semli puts the object in Loro's room...and Loro gets a nasty surprise after connecting. Neato eh! Note that "player" will be the person speaking (Loro in this case), because "player" is set to whoever initiates the action, and can only be changed by wiz-permed verbs. Generally, it stays the same from the task's start to it's finish. Now, if Loro had tested caller_perms(), then Semli's call would have been caught as one that did not have permission to be recycling objects. Got it? What's the most secure test for +x non-command line verbs? if (caller != this) When in doubt, use this one. It's the least flexible but the most secure. How do I do permissions-based security for a +x command line verb? The problem here is that you can't test caller_perms() on a command line verb, since the perms will be #-1. Note that this isn't a problem for object-based security, since "caller" for a command line verb will be the same as "player." To test security on a +x command line verb, replace "player" in a construct like: if (!$perm_utils:controls(player,this)) with an expression that will handle both command line and verb calls: if (!$perm_utils:controls( (valid(caller_perms())?caller_perms()|player) ,this)) Note that if caller_perms is #-1, then "player" is used, otherwise caller_perms is used. Why are +x verbs called using pass() a special case? One of the great things about MOO code is that the object-oriented nature lets you "cover" verbs by adding verbs of the same name on child objects. These can handle special cases, but otherwise simply pass(@args) down to the verb on the parent object instead. The problem is that if you use only perms-based security, this call (a legitimate one) will fail. Let's say you are testing with if (!$perm_utils:controls(caller_perms(),this)) which is generally very reasonable. If someone makes a new generic as a child of your verb, then caller_perms() will be that person, who is unlikely to "control" the object. The solution is to use a combination object-based and perms-based test such as: if ( (caller==this) || !$perm_utils:controls(caller_perms(),this) ) What sort of combination security tests are reasonable? Here's an example for us to dissect: if ( (caller!=this) && !$perm_utils:controls(cp=caller_perms(),this) && (cp!=$code_utils:verb_perms())) What's going on here? First, there's a test to see if caller!=this. That gives access to calls from other verbs on the same object and to calls via pass(). Then we check with $perm_utils:controls, which gives access to the object's owner, any additional owners, and to wizards. Finally, we test if the caller_perms are the same as the perms of the verb running \ (ie. the calling verb was written by us). This allows us to design objects that interact with each other. Note that this is a special circumstance, but one that's not terribly uncommon (eg. a class of objects and a feature object that interacts with them). =================== 10.7 Permissions (by Defender) Acknowledgement: This text is a formatted version of a message posted to *programmers on (now defunct) Worldmoo on Sat Mar 4 07:50:23 1995 PST by Defender (#160) 1. Every object, verb, and property has an owner. 2. Verbs are executed with a 'set of permissions', or a flag indicating which player owns the task. Any verb you write will normally run with your permissions, which means it can affect things you own. Wizards can use a built-in function called set_task_perms(), documented, to change the permissions of a particular verb's execution. This doesn't change the verb ownership, nor does it change permissions for other verbs. Normally you don't need to worry about that. 3. A verb with the permissions of the owner of something, or a wizard's permissions, can affect that something (read its value or write to it). For instance, you can create verbs and properties on objects you own, because the creative verbs run with your permissions. 4. Everything (objects, verbs, and properties) have a set of possible 'permission bits', which control access to them. Two of these potential bits are always R and W (for Readable and Writable). For verbs whose permissions aren't the owner and aren't wizardly, these flags are important. 5. If the R bit for something is set, any set of permissions can read it. For example, if a verb you write has its R bit set, anybody can read the verb code. If it is not set, the object/verb/property is said to be "E_PERM'ed", referring to the error code E_PERM (Permission Denied), which will be returned upon attempts to read the value. Unless you are deliberately needing to hide some information, it is good practice to make things readable by setting the R bit. 6. If the W bit for something is set, any set of permissions can write to it. For example, if you have a property whose W bit is set, anybody can set the property value to anything they want, or remove it altogether. The W bit is almost never set, and should NOT be set for verbs in particular. 7. What reading and writing mean depends on what you are dealing with. WHAT READABILITY MEANS WHAT WRITABILITY MEANS Objects: You can use verbs() and You can define your own verbs properties() directly to and properties on the object, read the list of verbs and which will be owned by you. properties directly. Verbs: You can use verb_info(), You can change the arguments, verb_args(), and names, and program code for the verb_code() on the verb, verb in question, using @edit and you can @list the code. for example. Properties: You can see the permissions You can change the permissions and value for the property. and value for the property. More on Permissions Brief review of permission bits: Objects - rwf r anyone can get a list of verbs and props on your obj. This doesn't mean they can actually read those verbs or props. (That is handled by the permissions of those verbs and props). f fertile w if the object is writable, this means that anyone could add or remove verbs or props from your object, even if your object is not readable. Verbs - rdxw r the verb is readable, anyone can @list your verb d debug bit. This means if verb hits an error, you get a traceback. x can the verb be called from other verbs (executable) w the verb is world writable. This means that anyone can change your verb code, but it still runs under the original author's permissions. This is almost always a BAD THING (tm). Properties - rcw r the property is world readable. w this means that anyone can write to your property (ie. change the value of your prop). Generally, w permission bits, whether on objs, verbs or props, is not a great idea, though of the 3, a +w prop is probably the least problematic, though I suppose it depends on how much of a problem you think someone changing the value of your prop might present. ;-) c this is perhaps the trickiest, (initially) of the different permission bits. If a prop is +c, anyone who creates a @kid of your object, will own the property. This means that they can directly change it, but also means that your verbs will no longer have permission to change it. So, the owner of a kid could change the prop with eval, or change the prop using @set. If you want YOUR verbs to be able to change the property, then you want so set the prop !c, so that you will be the owner of the prop for any kids.